package com.tool.genxml.handler;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import com.tool.genxml.entity.Component;
import com.tool.genxml.entity.MergedRegion;
import com.tool.genxml.entity.XRow;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static com.tool.genxml.constant.SysConstant.LEFT_BOLD_BRACKET;
import static com.tool.genxml.constant.SysConstant.RIGHT_BOLD_BRACKET;

/**
 * @author: zhoubin
 * @date: 2024/3/28
 */
public class ComponentSheetHandler extends ComponentHandler {

    /**
     * 组件列表
     */
    private Map<String, Component> components = new HashMap<>();

    public ComponentSheetHandler(XSSFSheet sheet) {
        super(sheet);
    }

    @Override
    public void analysisSheet() {
        int rowNum = getSheet().getPhysicalNumberOfRows();

        Component component = null;

        for (int i = 0; i < rowNum;) {
            XSSFRow row = getSheet().getRow(i);
            String componentName = row.getCell(0).toString();
            if (componentName.startsWith(LEFT_BOLD_BRACKET)) {
                component = new Component();
                componentName = componentName.substring(componentName.indexOf(LEFT_BOLD_BRACKET) + 1,
                        componentName.indexOf(RIGHT_BOLD_BRACKET));
                component.setName(componentName);
                components.put(componentName, component);

                i += 2;
                continue;
            }

            // 获取当前行所有单元格
            Map<Integer, MergedRegion> rowRegions = getRowRegion(i);
            // 判断是否为合并单元格，如果不是合并的单元格，则该行的后面的所有单元格都不是合并的单元格。
            if (CollUtil.isEmpty(rowRegions)) {
                XRow xRow = XRow.of(row);

                // 根据当前行是否含有组件标识当前组件
                markComponent(component, xRow);

                component.getXRowList().add(xRow);
                i++;
            } else {
                // 获取当前行的合并单元格的总行数
                int lineCount = rowRegions.get(0).getLineCount();
                // 组装带有合并单元格的行
                XRow xRow = assembleXRow(row, rowRegions);

                markComponent(component, xRow);

                component.getXRowList().add(xRow);

                // 下一次循环从合并单元格的下一个单元格开始计算
                i += lineCount;
            }
        }
    }

    /**
     * 标记组件，判断当前行是否含有组件，如果含有组件，则将组件标识置为1
     * @param component
     * @param xRow
     */
    private void markComponent(Component component, XRow xRow) {
        // 如果当前组件含有其他组件，标记一下
        if (!component.isHasComponent() && xRow.isHasComponent()) {
            component.setHasComponent(xRow.isHasComponent());

            if (!isHasComponent()) {
                setHasComponent(xRow.isHasComponent());
            }
        }
    }

    @Override
    public List<XRow> assembleComponent(List<XRow> xRowList) {
        if (CollUtil.isEmpty(xRowList)) {
            return xRowList;
        }

        // 由于需要在列表中添加组件的列，所以直接使用新的列表
        List<XRow> newRowList = new ArrayList<>();

        for (int i = 0; i < xRowList.size(); i++) {

            // 将原来的列放入列表中
            XRow xRow = xRowList.get(i);
            newRowList.add(xRow);

            // 装配组件
            if (xRow.isHasComponent()) {
                // 将原来组件设为false
                xRow.setHasComponent(false);

                // 根据组件名获取组件列表
                String componentName = xRow.getComponentName();
                Component component = components.get(componentName);

                // 当组件中的组件还含有组件时，直接装配内部组件的组件
                if (component.isHasComponent()) {
                    List<XRow> compXRowList = assembleComponent(component.getXRowList());
                    component.setXRowList(compXRowList);
                }

                List<XRow> compXRowList = component.getXRowList();

                // 遍历组件列表，将组件列表中的列放入新的列表中
                // 并将列的等级加2
                for (XRow row : compXRowList) {
                    XRow newRow = BeanUtil.toBean(row, XRow.class);
                    newRow.setLevel(xRow.getLevel() + newRow.getLevel() + 2);
                    newRowList.add(newRow);
                }
            }
        }

        return newRowList;
    }

    @Override
    public void assembleComponent() {
        if (!isHasComponent()) {
            return;
        }

        for (Component component : components.values()) {
            if (component.isHasComponent()) {
                List<XRow> xRowList = assembleComponent(component.getXRowList());
                component.setXRowList(xRowList);
                component.setHasComponent(false);
            }
        }
    }
}
